﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Text.RegularExpressions;
using Ehai.Web.Framework;
using Ehai.Web.Framework.Rules;
using System.Diagnostics;


namespace Ehai.Web.Framework
{

    #region 消息处理类

    /// <summary>
    /// 消息处理类
    /// </summary>
    public class MessageDataTreator
    {

        #region 公有变量

        /// <summary>
        /// 存放将大请求分割后的字段
        /// </summary>
        public string[] ArrMsgs = null;

        /// <summary>
        /// 存放要返回前台的数据
        /// </summary>
        public string[][][] ReturnDatas = null;

        /// <summary>
        /// 标示处理到那条小消息,用于替代前面消息的结果时
        /// </summary>
        public int ii = 0;

        /// <summary>
        /// 初始化 ContextInfo Ci
        /// </summary>
        public Ehai.Web.Framework.ContextInfo Ci = null;

        #endregion

        #region 替代大请求中的参数

        /// <summary>
        /// 替代大请求中的参数
        /// </summary>
        /// <param name="m">单个正则表达式匹配的结果</param>
        /// <returns>需要的参数值</returns>
        public string ReplacePM(Match m)
        {
            try
            {
                int i = Convert.ToInt32(m.Groups[1].Value);
                return i < ArrMsgs.Length && i > 0 ? ArrMsgs[i] : m.Value;
            }
            catch { }
            return m.Value;
        }

        #endregion

        #region 替代以QueryString和Form为变量的字符串

        /// <summary>
        /// 替代以QueryString和Form为变量的字符串
        /// </summary>
        /// <param name="m">单个正则表达式匹配的结果</param>
        /// <returns>需要的字符串</returns>
        public string ReplaceQueryForm(Match m)
        {
            try
            {
                string re = Ci.Parameters(m.Groups[1].Value);
                return re == null ? m.Value : re;
            }
            catch { }
            return m.Value;
        }

        #endregion

        #region 替代常量的字典

        /// <summary>
        /// 替代常量的字典
        /// </summary>
        /// <param name="m">单个正则表达式匹配的结果</param>
        /// <returns>需要的常量</returns>
        public string ReplaceStatic(Match m)
        {
            string re = String.Empty;
            switch (m.Groups[1].Value)
            {
                case "now":
                    re = DateTime.Now.ToString();
                    break;
            }
            return String.IsNullOrEmpty(re) ? m.Value : re;
        }

        #endregion

        #region 替代函数,包含替代Session、Application、Cache、前面消息的结果、运算的字符串

        /// <summary>
        /// 替代函数,包含替代Session、Application、Cache、前面消息的结果、运算的字符串
        /// </summary>
        /// <param name="singleMsg">需要替代的字符串</param>
        /// <returns>替代后的字符串</returns>
        public string ReplaceSysVarible(string singleMsg)
        {

            // 替代Session,Application,Cache
            Regex rg4 = new Regex(@"([@:!])\[([a-zA-Z0-9]+)\]\1");
            if (rg4.IsMatch(singleMsg))
                singleMsg = rg4.Replace(singleMsg, new MatchEvaluator(replaceSeApliCa));

            if (ii > 0)
            {
                // 替代前面消息的结果(包含指明消息号 和 未指明消息号,默认使用前一条消息号)
                Regex rg5 = new Regex(ContantChar.RgxArrXyz);
                if (rg5.IsMatch(singleMsg))
                    singleMsg = rg5.Replace(singleMsg, new MatchEvaluator(replaceFormerData));
            }

            // 替代需要运算的字符串
            Regex rg6 = new Regex(@"{([\d\+\-\*\(\)\.]+)}");
            if (rg6.IsMatch(singleMsg))
                singleMsg = rg6.Replace(singleMsg, new MatchEvaluator(replaceCalculate));

            return singleMsg;

        }

        #region 替代Session,Application,Cache

        /// <summary>
        /// 替代Session,Application,Cache 
        /// </summary>
        /// <param name="m">单个正则表达式匹配的结果</param>
        /// <returns>需要的Session,Application,Cache</returns>
        private string replaceSeApliCa(Match m)
        {
            object re = String.Empty;
            switch (m.Groups[1].Value)
            {
                case "@":
                    // 替代Session
                    re = Ci.GetGlobalSession(m.Groups[2].Value);
                    break;
                case ":":
                    // 替代Application
                    re = Ci.Application[m.Groups[2].Value];
                    break;
                case "!":
                    // 替代Cache
                    re = Ci.Cache[m.Groups[2].Value];
                    break;
            }
            return re == null ? m.Value : re.ToString();
        }

        #endregion

        #region 替代前面消息的结果

        /// <summary>
        /// 替代前面消息的结果
        /// </summary>
        /// <param name="m">单个正则表达式匹配的结果</param>
        /// <returns>需要前面消息的结果</returns>
        private string replaceFormerData(Match m)
        {
            try
            {
                int n = m.Groups[1].Value.Trim() == String.Empty ? ii - 1 : Convert.ToInt32(m.Groups[1].Value) - 1;
                int x = Convert.ToInt32(m.Groups[2].Value) - 1;
                int y = Convert.ToInt32(m.Groups[3].Value) - 1;
                if ((ReturnDatas != null && n >= 0 && n < ReturnDatas.Length) &&
                    (ReturnDatas[n] != null && x >= 0 && x < ReturnDatas[n].Length) &&
                    (ReturnDatas[n][x] != null && y >= 0 && y < ReturnDatas[n][x].Length))
                    return (ReturnDatas[n][x][y]).ToString();
            }
            catch { }
            return m.Value;
        }

        #endregion

        #region 替代需要运算的字符串

        /// <summary>
        /// 替代需要运算的字符串
        /// </summary>
        /// <param name="m">单个正则表达式匹配的结果</param>
        /// <returns>完成运算的字符串</returns>
        private string replaceCalculate(Match m)
        {
            try
            {
                return CalcByExpression.Calculate(m.Groups[0].Value).ToString();
            }
            catch { }
            return m.Value;
        }

        #endregion

        #endregion

    }

    #endregion

    #region 返回html处理类

    /// <summary>
    /// 返回html处理类
    /// </summary>
    public class ResponseHtmlTreator
    {
        #region 公有变量

        /// <summary>
        /// 保存 Message Format string 
        /// </summary>
        public string Mfmt = null;

        /// <summary>
        /// 保存 Error Format string  
        /// </summary>
        public string Efmt = null;

        /// <summary>
        /// 消息处理时产生的错误信息
        /// </summary>
        public string ErrInfo = null;

        /// <summary>
        /// 消息处理类对象
        /// </summary>
        public MessageDataTreator Mdt = null;

        #endregion

        #region 私有变量

        private string body = String.Empty;
        private string head = String.Empty;
        private string tail = String.Empty;
        private int curPos = 0;

        #endregion

        #region 替代body head tail中所要返回的结果标示

        private string replaceBht(string str)
        {
            if (String.IsNullOrEmpty(str)) return String.Empty;

            Regex rg6 = new Regex(@"\#A([\d]+)\#"); //.#A1#..#A2#
            if (rg6.IsMatch(str))
                str = rg6.Replace(str, new MatchEvaluator(replaceBhtA));

            Regex rg7 = new Regex(ContantChar.RgxArrXyz); //#1,1#....#1,1,1#
            if (rg7.IsMatch(str))
                str = rg7.Replace(str, new MatchEvaluator(replaceBhtNNN));

            Regex rg8 = new Regex(@"\#K,(\d+)\#"); //#1,K#.....#1,K,1#
            if (rg8.IsMatch(str))
            {
                StringBuilder sb = new StringBuilder();
                int l = Mdt.ReturnDatas.Length - 1;
                for (curPos = 0; curPos < l; curPos++)
                {
                    sb.Append(rg8.Replace(str, new MatchEvaluator(replaceBhtNKN)));
                }
                str = sb.ToString();
            }

            return str;
        }

        #region 替代 A

        private string replaceBhtA(Match m)
        {
            int x1 = Convert.ToInt32(m.Groups[1].Value) - 1;

            if (x1 >= 0 && x1 < Mdt.ReturnDatas.Length && Mdt.ReturnDatas[x1] != null)
            {
                return ReturnStringFromArray.ReStringFromTwoDmArr(Mdt.ReturnDatas[x1]);
            }

            return m.Value;
        }

        #endregion

        #region 替代 NNN

        private string replaceBhtNNN(Match m)
        {
            int x1 = m.Groups[1].Value == String.Empty ? Mdt.ReturnDatas.Length - 1 : Convert.ToInt32(m.Groups[1].Value) - 1;
            int x2 = Convert.ToInt32(m.Groups[2].Value) - 1;
            int x3 = Convert.ToInt32(m.Groups[3].Value) - 1;

            if ((x1 >= 0 && x1 < Mdt.ReturnDatas.Length) &&
                (x2 >= 0 && x2 < Mdt.ReturnDatas[x1].Length) &&
                (x3 >= 0 && x3 < Mdt.ReturnDatas[x1][x2].Length))
            {
                return Mdt.ReturnDatas[x1][x2][x3];
            }
            return m.Value;
        }


        #endregion

        #region 替代 NKN

        private string replaceBhtNKN(Match m)
        {
            int x1 = Mdt.ReturnDatas.Length - 1;
            int x3 = Convert.ToInt32(m.Groups[1].Value) - 1;
            if (x3 >= 0 && x3 < Mdt.ReturnDatas[x1][curPos].Length && Mdt.ReturnDatas[x1][curPos][x3] != null)
                return Mdt.ReturnDatas[x1][curPos][x3];
            return m.Value;
        }

        #endregion

        #endregion

        #region 所有消息处理成功时调用的返回函数

        /// <summary>
        /// 所有消息处理成功时调用的返回函数
        /// </summary>
        /// <returns>返回所要的消息处理结果字符串</returns>
        public string GetReponseHtml()
        {
            if (Mfmt == null)
            {
                if (Mdt.ReturnDatas != null)
                {
                    StringBuilder r = new StringBuilder();
                    if (Mdt.ReturnDatas.Length == 1)
                        r.Append(ReturnStringFromArray.ReStringFromTwoDmArr(Mdt.ReturnDatas[0]));

                    else r.Append(ReturnStringFromArray.ReStringFromThreeDmArr(Mdt.ReturnDatas));

                    return r.ToString();
                }
            }
            else
            {
                string[] arrMfmt = Mfmt.Split(ContantChar.SplitParamChars);
                if (arrMfmt.Length > 0) body = arrMfmt[0];
                if (arrMfmt.Length > 1) head = arrMfmt[1];
                if (arrMfmt.Length > 2) tail = arrMfmt[2];

                StringBuilder t = new StringBuilder();
                if (Mdt.ReturnDatas != null)
                {
                    t.Append(replaceBht(head));
                    t.Append(replaceBht(body));
                    t.Append(replaceBht(tail));
                }
                return t.ToString();

            }
            return String.Empty;
        }

        #endregion

        #region 消息处理错误时调用的返回函数

        /// <summary>
        /// 消息处理错误时调用的返回函数
        /// </summary>
        /// <returns>返回消息处理时产生的错误信息</returns>
        public string GetErrorReponseHtml()
        {
            if (Efmt == null)
                return "{error :\"" + Ehai.Web.Framework.UtilTools.TwiceEscapeString(ErrInfo.ToString()) + "\"}";
            else
                return Efmt.Replace("#error#", ErrInfo.ToString());
        }

        #endregion
    }

    #endregion

    #region 请求处理入口类

    /// <summary>
    /// 请求处理入口类
    /// </summary>
    sealed class MessageHandle
    {

        #region 私有变量

        private static Ehai.Web.Framework.ContextInfo _ci = null;
        // 定义消息处理类对象
        private MessageDataTreator mdt = new MessageDataTreator();
        private ResponseHtmlTreator rht = new ResponseHtmlTreator();

        #endregion

        #region ResponseHtmlString

        private StringBuilder responseHtmlString = new StringBuilder();

        /// <summary>
        /// ResponseHtmlString
        /// </summary>
        public StringBuilder ResponseHtmlString
        {
            get
            {
                return responseHtmlString;
            }
        }

        #endregion

        #region 搭建测试环境

        [Conditional("TESTVIROMENT")]
        private void tv1()
        {

#if DEBUG

            // 测试获得帮助信息
            Rules.HelpInfo.GetAllMsgInfo();
            Rules.HelpInfo.GetHelpDetail("dir");
            Rules.HelpInfo.GetParametersInfo("dir");

#endif

            // 测试将数组转字符串的函数
            string[] arr1 = { "ex1,ex2,ex3" };
            string[][] arr2 = new string[3][];
            string[][][] arr3 = new string[3][][];
            arr2[0] = new string[] { "ex11", "ex12", "ex13" };
            arr2[1] = new string[] { "ex21", "ex22", "ex23" };
            arr2[2] = new string[] { "ex31", "ex32", "ex33" };
            arr3[0] = new string[][] { arr1, arr1, arr1 };
            string r1 = Rules.ReturnStringFromArray.ReStringFromOneDmArr(arr1);
            string r2 = Rules.ReturnStringFromArray.ReStringFromTwoDmArr(arr2);
            string r3 = Rules.ReturnStringFromArray.ReStringFromThreeDmArr(arr3);

            // 测试指定msg
            //msg = "'[p2]'|,xxccdcd|";

            // 测试Session,Application,Cache
            _ci.Session["userSession"] = "zhangsan";
            _ci.Application["userApp1"] = "app1";
            _ci.Application["userApp2"] = "app2";
            _ci.Cache["userCache"] = "cache1";
        }

        #endregion

        /// <summary>
        /// 请求处理的入口函数
        /// </summary>
        /// <param name="ci">ContextInfo类型</param>
        /// <returns>
        /// 0:正常处理完毕<br />
        /// -1:没有消息<br />
        /// -2:有消息但是没有处理程序<br />
        /// </returns>
        public int HandleEntry(ContextInfo ci)
        {
            #region 初始化

            if (_ci == null) _ci = ci;
            mdt.Ci = _ci;
            rht.Mdt = mdt;

            #endregion

            #region 保存消息字符串msg

            string msg = _ci.Parameters("msg");
            if (msg == null) return -1;
            msg = msg.ToString().Trim();
            if (msg == String.Empty) return -2;

            #endregion

            #region 保存并解码 Message Format string 和 Error Format string

            // 判断是否传mfmt,若没有则使用默认格式,并解码
            if (!String.IsNullOrEmpty(_ci.Parameters("mfmt")))
                rht.Mfmt = HttpUtility.UrlDecode(_ci.Parameters("mfmt"));


            // 判断是否传efmt,若没有则使用默认格式,并解码
            if (!String.IsNullOrEmpty(_ci.Parameters("efmt")))
                rht.Efmt = HttpUtility.UrlDecode(_ci.Parameters("efmt"));

            #endregion

            #region 搭建测试环境1

            tv1();

            #endregion

            #region RELEASE：从字典中获取消息对应的字符串,还原大请求  /************** 未完成 ***************/

#if RELEASE
            //将大请求还原成各消息的组合字符串
            msg = getStringFromDict(msg);
#endif

            #endregion

            #region 将大请求解码

            msg = HttpUtility.UrlDecode(msg);

            #endregion

            #region 将大请求分割

            mdt.ArrMsgs = msg.Split(ContantChar.SplitParamChars);
            msg = mdt.ArrMsgs[0];

            #endregion

            #region 替代大请求参数

            Regex rg1 = new Regex(@"\#(\d+)\#");
            if (rg1.IsMatch(msg))
                msg = rg1.Replace(msg, new MatchEvaluator(mdt.ReplacePM));

            #endregion

            #region 替代QueryString或者Form的变量

            Regex rg2 = new Regex(@"`\[([a-zA-Z0-9]+)\]`");
            if (rg2.IsMatch(msg))
                msg = rg2.Replace(msg, new MatchEvaluator(mdt.ReplaceQueryForm));

            #endregion

            #region 替代常量

            Regex rg3 = new Regex(@"@([a-zA-Z0-9]+)@");
            if (rg3.IsMatch(msg))
                msg = rg3.Replace(msg, new MatchEvaluator(mdt.ReplaceStatic));

            #endregion

            #region 将大请求分割成小请求

            //arrMsgSingle 存放分割完成的各小消息字符串
            string[] arrMsgSingle = msg.Split(ContantChar.SplitSmallMsgs, StringSplitOptions.RemoveEmptyEntries);

            #endregion

            #region 循环处理各个小消息

            if (arrMsgSingle.Length <= 0) return 0;

            try
            {
                // 存放要返回前台的数据
                mdt.ReturnDatas = new string[arrMsgSingle.Length][][];

                // 循环处理各个小消息
                for (mdt.ii = 0; mdt.ii < arrMsgSingle.Length; mdt.ii++)
                {
                    // 进入替代函数,替代Session,Application、Cache、前面消息的结果、运算的字符串 
                    arrMsgSingle[mdt.ii] = mdt.ReplaceSysVarible(arrMsgSingle[mdt.ii]);
                    // 将小消息内部分割
                    string[] t = arrMsgSingle[mdt.ii].Split(ContantChar.SplitSingleMsg, StringSplitOptions.None);
                    // 判断规则类型,创造相应的接口
                    IMsgRuleHandle imr = RuleHandleFactory.Create(t[0]);
                    // 进入相应的处理函数
                    if (imr != null)
                        mdt.ReturnDatas[mdt.ii] = imr.Execute(t, _ci);
                    else
                        return -2;
                }
            }
            catch (Ehai.Web.Framework.WebException we)
            {
                rht.ErrInfo = we.GetResponseInfo();
            }
            catch (Exception ex)
            {
                throw new Ehai.Web.Framework.WebException("Ehai.WebFramework.MessageHandle", "规则处理流程中出现错误", ex);
            }

            #endregion

            #region 形成返回字符串

            if (rht.ErrInfo == null)
            {
                // 所有消息处理成功,调用返回函数
                responseHtmlString.Append(rht.GetReponseHtml());
            }
            else
            {
                // 消息处理错误,调用返回错误的函数
                responseHtmlString.Append(rht.GetErrorReponseHtml());
            }

            #endregion

            return 0;

        }

    }

    #endregion 请求处理入口类END

}
